package com.youlu.campus.service.order;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.google.common.collect.Lists;
import com.youlu.campus.base.exception.BusinessException;
import com.youlu.campus.entity.DigitalCaOrder;
import com.youlu.campus.entity.FileExportTask;
import com.youlu.campus.entity.UserCaRecord;
import com.youlu.campus.entity.UserPO;
import com.youlu.campus.entity.VO.req.DigitalCaOrderReq;
import com.youlu.campus.entity.VO.res.DigitalCaOrderExport;
import com.youlu.campus.entity.english.vo.request.CompetitionCaCollectRequest;
import com.youlu.campus.entity.order.SharingProfitOrderDetail;
import com.youlu.campus.entity.system.UserDataPermission;
import com.youlu.campus.service.file.FileExportTaskService;
import com.youlu.campus.service.file.FileService;
import com.youlu.campus.service.system.UserDataPermissionService;
import lombok.extern.slf4j.Slf4j;
import ma.glasnost.orika.MapperFacade;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.repository.support.PageableExecutionUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.io.*;
import java.util.*;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

@Slf4j
@Service
public class DigitalCaOrderDetailService {

    @Autowired
    private MongoTemplate mongoTemplate;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private MerchantSharingProfitService merchantSharingProfitService;

    @Resource(name = "masterMongoTemplate")
    private MongoTemplate masterMongoTemplate;

    /**
     * 获取缓存中信息
     */
    private static final String PLACE_ORDER_CACHE = "campus:digitalCaOrder:receive:%s:user:%s:caType:%s:caLevel:%s";

    private final static String MOBILE_REGEX = "(\\d{3})\\d{4}(\\d{4})";

    @Autowired
    private UserDataPermissionService userDataPermissionService;

    @Autowired
    private FileExportTaskService fileExportTaskService;

    @Autowired
    private MapperFacade mapperFacade;

    @Autowired
    private FileService fileService;


    public void exportCaOrder(DigitalCaOrderReq dto) {
        String optUserName = dto.getOptUserName();
        log.info("【电子订单导出】start 导出 optUserName:{}", optUserName);
        Integer pageNo = 1;
        Integer pageSize = 2000;
        String fileExportTaskId = "";
        String fileName = "";
        List<DigitalCaOrder> caOrderList = null;
        Boolean createFileTask = Boolean.FALSE;
        List<DigitalCaOrderExport> exportResult = Lists.newLinkedList();
        while (true) {
            dto.setPageNo(pageNo);
            dto.setPageSize(pageSize);
            log.info("【电子订单导出】查询第几页 page:{} 导出 optUserName:{}", pageNo, optUserName);
            Page<DigitalCaOrder> pageDigitalCaOrder = this.list(dto);
            caOrderList = pageDigitalCaOrder.getContent();
            if (CollectionUtils.isEmpty(caOrderList)) {
                log.info("【电子订单导出】end 导出 optUserName:{}", optUserName);
                break;
            }
            if (!createFileTask) {
                log.info("【电子订单导出】 创建文件导出任务 optUserName:{}", optUserName);
                FileExportTask fileExportTask = new FileExportTask();
                fileExportTask.setToken(optUserName);
                fileExportTask.setBizType("digital-ca-order");
                fileExportTask.setStatus(0);
                fileExportTask.setOptUser(optUserName);
                fileExportTask.setOptUserId(dto.getUserId());
                fileName = "电子版订单明细-" + System.currentTimeMillis() + ".xlsx";
                fileExportTask.setFileName(fileName);
                fileExportTask.setNum((int) pageDigitalCaOrder.getTotalElements());
                fileExportTask.setDesc("电子版订单明细");
                fileExportTaskId = fileExportTaskService.create(fileExportTask);
                createFileTask = Boolean.TRUE;
            }
            caOrderList.stream().forEach(digitalCaOrder -> {
                DigitalCaOrderExport orderExport = mapperFacade.map(digitalCaOrder, DigitalCaOrderExport.class);
                if (0 == digitalCaOrder.getStatus()) {
                    orderExport.setStatus("未支付");
                } else {
                    orderExport.setStatus("已支付");
                }
                if (StringUtils.isNotBlank(digitalCaOrder.getMobile())) {
                    Query caQuery = new Query();
                    caQuery.addCriteria(Criteria.where("mobile").is(digitalCaOrder.getMobile()));
                    caQuery.addCriteria(Criteria.where("activityId").is(digitalCaOrder.getActivityId()));
                    List<UserCaRecord> caRecordList = this.mongoTemplate.find(caQuery, UserCaRecord.class);
                    if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(caRecordList)) {
                        UserCaRecord userCaRecord =
                                caRecordList.stream().filter(userCa -> userCa.getLevelName().equals(digitalCaOrder.getCaLevel())).findFirst().orElse(null);
                        if (Objects.nonNull(userCaRecord)) {
                            orderExport.setCertificateNo(userCaRecord.getCertificateNo());
                        }
                    }
                }
                exportResult.add(orderExport);
            });
            pageNo++;
        }
        if (CollectionUtils.isEmpty(exportResult)) {
            log.info("【电子订单导出】end 导出  未找到数据 optUserName:{}", optUserName);
            return;
        }
        ExcelWriter excelWriter = null;
        String file = "/data/app/file/" + fileName;
        try {
            excelWriter = EasyExcel.write(file, DigitalCaOrderExport.class).build();
            WriteSheet writeSheet = EasyExcel.writerSheet(1, "电子订单明细表").build();
            excelWriter.write(exportResult, writeSheet);
        } catch (Exception e) {
            log.info("【电子订单导出】end 导出 错误 optUserName:{}", optUserName, e);
        } finally {
            if (Objects.nonNull(excelWriter)) {
                excelWriter.finish();
            }
            exportResult.clear();
        }
        File newFile = new File(file);
        if (!newFile.exists()) {
            log.error("找不到渠道分销订单明细表文件");
            return;
        }
        InputStream in = null;
        try {
            in = new FileInputStream(newFile);
            String url = fileService.uploadFile(in, fileName);
            Query queryTask = new Query().addCriteria(Criteria.where("id").is(fileExportTaskId));
            Update update = new Update();
            update.set("status", 1);
            update.set("url", url);
            update.set("updatedTime", new Date());
            mongoTemplate.updateFirst(queryTask, update, FileExportTask.class);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            log.error("导出电子订单明细表 error", e);
            return;
        } catch (Exception e) {
            e.printStackTrace();
            log.error("导出电子订单明细表 error", e);
            return;
        } finally {
            if (Objects.nonNull(in)) {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        log.info("【电子订单导出】end 导出 optUserName:{}", optUserName);
    }

    public Boolean getBuyOrderByUserId(String userId) {
        Query query = new Query();
        query.addCriteria(Criteria.where("userId").is(userId));
        query.addCriteria(Criteria.where("status").is(1));
        return this.mongoTemplate.exists(query, DigitalCaOrder.class);
    }


    public Page<DigitalCaOrder> list(DigitalCaOrderReq digitalCaOrderReq) {
        PageRequest pageRequest = PageRequest.of(digitalCaOrderReq.getPageNo() - 1, digitalCaOrderReq.getPageSize());
        Query query = new Query();
        if (StringUtils.isNotBlank(digitalCaOrderReq.getUserName())) {
            Pattern pattern = Pattern.compile("^.*" + digitalCaOrderReq.getUserName() + ".*$",
                    Pattern.CASE_INSENSITIVE);
            query.addCriteria(Criteria.where("name").regex(pattern));
        }
        if (StringUtils.isNotBlank(digitalCaOrderReq.getMobile())) {
            query.addCriteria(Criteria.where("mobile").is(digitalCaOrderReq.getMobile()));
        }
        String orderNo = digitalCaOrderReq.getOrderNo();
        if (StringUtils.isNotBlank(orderNo)) {
            query.addCriteria(Criteria.where("orderNo").is(orderNo));
        }
        if (Objects.nonNull(digitalCaOrderReq.getStatus())) {
            query.addCriteria(Criteria.where("status").is(digitalCaOrderReq.getStatus()));
        } else {
            query.addCriteria(Criteria.where("status").is(1));
        }

        Date startPayTime = digitalCaOrderReq.getStartPayTime();
        Date endPayTime = digitalCaOrderReq.getEndPayTime();
        if (Objects.nonNull(startPayTime) && Objects.nonNull(endPayTime)) {
            query.addCriteria(Criteria.where("payTime").gte(startPayTime).lte(endPayTime));
        }
        UserDataPermission req = new UserDataPermission();
        req.setUserId(digitalCaOrderReq.getUserId());
        List<UserDataPermission> datas = userDataPermissionService.list(req);
        if (CollectionUtils.isEmpty(datas) || CollectionUtils.isEmpty(datas.get(0).getActivityId())) {
            return PageableExecutionUtils.getPage(new ArrayList<>(), pageRequest, () -> 0L);
        }
        Set<String> activityIdSet = datas.get(0).getActivityId().stream().collect(Collectors.toSet());
        if (StringUtils.isNotBlank(digitalCaOrderReq.getActivityId())) {
            //如果活动存在分配权限中则查询
            if (activityIdSet.contains(digitalCaOrderReq.getActivityId())) {
                query.addCriteria(Criteria.where("activityId").is(digitalCaOrderReq.getActivityId()));
            } else {
                return PageableExecutionUtils.getPage(new ArrayList<>(), pageRequest, () -> 0L);
            }
        } else {
            query.addCriteria(Criteria.where("activityId").in(activityIdSet));
        }
        long count = this.mongoTemplate.count(query, DigitalCaOrder.class);
        if (count == 0) {
            return PageableExecutionUtils.getPage(new ArrayList<>(), pageRequest, () -> count);
        }
//        query.with(new Sort(Sort.Direction.DESC, "createdTime"));
        Sort sort=Sort.by(Sort.Direction.DESC, "createdTime");
        query.with(sort);
        List<DigitalCaOrder> orderList = this.mongoTemplate.find(query.with(pageRequest), DigitalCaOrder.class);
        orderList.forEach(digitalCaOrder -> {
            if (StringUtils.isNotBlank(digitalCaOrder.getMobile())) {
                if (digitalCaOrderReq.getMobileHide()) {//手机号是否要隐藏
                    digitalCaOrder.setMobile("");
                } else {
                    if (digitalCaOrderReq.getMobileDesensitization()) {//手机号是否要脱敏
                        digitalCaOrder.setMobile(digitalCaOrder.getMobile().replaceAll(MOBILE_REGEX, "$1****$2"));
                    }
                }
            }
            SharingProfitOrderDetail sharingProfitOrderDetail =
                    merchantSharingProfitService.getSharingProfitAmountByOrderNo(digitalCaOrder.getOrderNo());
            if (Objects.nonNull(sharingProfitOrderDetail)) {
                digitalCaOrder.setSharingProfitStatus(sharingProfitOrderDetail.getSharingProfitStatus());
                Integer sharingProfitAmount = sharingProfitOrderDetail.getSharingProfitAmount();
                digitalCaOrder.setSharingProfitAmount(sharingProfitAmount);
            } else {
                digitalCaOrder.setSharingProfitStatus(5);
            }
        });
        return PageableExecutionUtils.getPage(orderList, pageRequest, () -> count);
    }


    public DigitalCaOrder findByUserIdAndCaTypeAndCaLevel(CompetitionCaCollectRequest caCollectReq) {
        if (Objects.isNull(caCollectReq)) {
            throw new BusinessException("参数错误");
        }
        String activityId = caCollectReq.getActivityId();
        String caType = caCollectReq.getCaType();
        String caLevel = caCollectReq.getCaLevel();
        UserPO currentUser = caCollectReq.getCurrentUser();
        if (StringUtils.isAnyBlank(activityId, caType, caLevel)) {
            log.error("【电子证书订单】DigitalCaOrderService.findByUserIdAndCaTypeAndCaLevel 参数存在为空 activityId->{}|caType " +
                    "->{} | caLevel->{}", activityId, caType, caLevel);
            throw new BusinessException("领取电子证书参数错误");
        }

        Query query = new Query();
        query.addCriteria(Criteria.where("userId").is(currentUser.getId()));
        query.addCriteria(Criteria.where("caType").is(caType));
        query.addCriteria(Criteria.where("activityId").is(activityId));
        query.addCriteria(Criteria.where("status").is(1));
        return masterMongoTemplate.findOne(query, DigitalCaOrder.class);
    }
}
